# -*- coding: utf-8 -*-
import re

import requests

from util.httpUtil import session

from util import stringUtil, aesUtil, configJsonUtil
from exception.exceptions import AuthenticationException
from util import httpUtil
from util.loggerFactory import Logger

JSESSIONID_IDS2_PATH = 'JSESSIONID_ids2=(.+); Path'
JSESSIONID_PATH = 'JSESSIONID=(.+); Path'
JSESSIONID_IDS_ = "JSESSIONID_ids2"
JSESSIONID = 'JSESSIONID'

logger = Logger()


class SSOService:

    def __init__(self, user_id=None, password=None, cache=True):
        config = configJsonUtil.get_config()
        self.account = config['account']
        if user_id is None:
            self.user_id = self.account['user_id']
        else:
            self.user_id = user_id
        if password is None:
            self.password = aesUtil.PrpCrypt.decrypt_password(self.account['user_id'], self.account['password'])
        else:
            self.password = password

        self.app_index = config['base']['app_index']
        self.app_session_key = config['base']['app_session_key']
        self.cas_server_sessionId = None
        self.app_session_value = None
        self.cache = cache
        if not self.cache:
            self.app_session_value = ''
            self.save_app_session_value()
        self.__login()
        # self.__load_user_name()

    def __login(self, times=3):
        logger.debug("单点登录获取app_session_value")
        if times > 0:
            self.app_session_value = configJsonUtil.get_config()['base']['app_session_value']
            if self.app_session_value == '':
                self.cas_server_sessionId, self.app_session_value = login_to_service(
                    self.app_index, self.user_id, self.password, True)
                self.save_app_session_value()
                logger.info('单点登录 app_session_value: %s' % self.app_session_value)
            else:
                # 已有会话，检查是否过期
                response = httpUtil.send_get_request(self.app_index, cookies=self.get_app_session_id())
                if response.status_code == 302:
                    logger.error("单点登录重新向返回内容:" + response.text)
                    # 过期清空 app_session_value
                    self.app_session_value = ''
                    self.save_app_session_value()
                    self.__login(times - 1)
        else:
            raise OSError('单点登录重定向次数超过上限，请检查')

    def save_app_session_value(self):
        config = configJsonUtil.get_config()
        config['base']['app_session_value'] = self.app_session_value
        configJsonUtil.save_json(config)

    def get_app_session_id(self):
        return {
            self.app_session_key: self.app_session_value
        }

    def __load_user_name(self):
        response = httpUtil.send_get_request("http://cas.wisedu.com/authserver/index.do", cookies={
            JSESSIONID_IDS_: self.cas_server_sessionId})
        if response.status_code == 200:
            div = stringUtil.get_first_matching_group_by_pattern(response.text, '<div class="auth_username">(.+)</div>')
            user_name = div.replace("<span>", '').replace("</span>", '').strip('')
            logger.debug(user_name)
            self.user_name = user_name

    def get_user_name(self):
        return self.user_name


def get_service_sessionId_redirectUrl(service_url):
    response = httpUtil.send_get_request(service_url)
    sessionId, redirectUrl = '', ''
    if 'set-cookie' in response.headers:
        cookieValue = response.headers['set-cookie']
        sessionId = stringUtil.get_first_matching_group_by_pattern(cookieValue, JSESSIONID_PATH)
    if 'location' in response.headers:
        redirectUrl = response.headers['location']
    return sessionId, redirectUrl


def cas_server_authentication(cas_server_url, userName="admin", userPasswd="admin", encrypt_pwd_flag=False):
    response1 = httpUtil.send_get_request(cas_server_url, allow_redirects=False)

    cas_server_sessionId = stringUtil.get_first_matching_group_by_pattern(response1.headers['set-cookie'],
                                                                          JSESSIONID_IDS2_PATH)
    response_text = str(response1.content, 'utf-8')
    lt = stringUtil.get_first_matching_group_by_pattern(response_text,
                                                        'name="lt" value="(.+)"')
    execution = stringUtil.get_first_matching_group_by_pattern(response_text,
                                                               'name="execution" value="(.+)"')

    pwdDefaultEncryptSalt = stringUtil.get_first_matching_group_by_pattern(response_text,
                                                                           'var pwdDefaultEncryptSalt = "(.+)";')
    if encrypt_pwd_flag:
        logger.debug('pwdDefaultEncryptSalt: ' + pwdDefaultEncryptSalt)
        encrypt_pwd = get_wrapped_pass(pwdDefaultEncryptSalt, userPasswd)
        logger.debug('encrypt_pwd: ' + encrypt_pwd)
    else:
        encrypt_pwd = userPasswd
    http_data_for_auth = {
        'username': userName,
        'password': encrypt_pwd,
        'lt': lt,
        '_eventId': 'submit',
        'dllt': 'userNamePasswordLogin',
        'execution': execution,
        'rmShown': '1',
        'rememberMe': 'on'
    }
    logger.debug('cas_server_url:' + cas_server_url)
    logger.debug(http_data_for_auth)
    response2 = httpUtil.send_post_request(cas_server_url, params=http_data_for_auth,
                                           cookies={JSESSIONID: cas_server_sessionId})
    if response2.status_code == 200:
        msg = stringUtil.get_first_matching_group_by_pattern(response2.text,
                                                             '<span id="msg" class="auth_error" style="top:-19px;">(.+)</span>')
        logger.error(msg)
        raise AuthenticationException(msg)
    else:
        casTicket = stringUtil.get_first_matching_group_by_pattern(response2.headers['set-cookie'],
                                                                   'CASTGC=(\S+);Path=\/authserver\/;')
        redirectUrl = response2.headers['location']
    return cas_server_sessionId, casTicket, redirectUrl


def redirect_to_service(service_url, service_sessionId):
    response = httpUtil.send_get_request(service_url, {JSESSIONID: service_sessionId}, allow_redirects=True)
    return response


def login_to_service(service_url, userName="admin", userPasswd="admin", encrpt_pwd_flag=False):
    httpUtil.session.close()
    httpUtil.session = requests.session()
    service_sessionId, redirectToCas = get_service_sessionId_redirectUrl(service_url)
    cas_server_sessionId, casTicket, redirectToServer = cas_server_authentication(redirectToCas,
                                                                                  userName,
                                                                                  userPasswd,
                                                                                  encrpt_pwd_flag)
    response = redirect_to_service(redirectToServer, service_sessionId)
    if response.status_code == 200:
        logger.debug("Login To Service Success")
    else:
        logger.debug("Login To Service Fail")
    key_ = configJsonUtil.get_config()['base']['app_session_key']
    value = ''
    if key_ in httpUtil.session.cookies:
        value = httpUtil.session.cookies[key_]
    return cas_server_sessionId, value


def get_wrapped_pass(pwdDefaultEncryptSalt, password):
    encrpt_pwd = aesUtil.PrpCrypt(pwdDefaultEncryptSalt, stringUtil.random_string(16)).encrypt(
        stringUtil.random_string(64) + password)
    return encrpt_pwd
